package com.itheima.prize.api.action;

import com.alibaba.fastjson.JSON;
import com.itheima.prize.api.config.LuaScript;
import com.itheima.prize.commons.config.RabbitKeys;
import com.itheima.prize.commons.config.RedisKeys;
import com.itheima.prize.commons.db.entity.*;
import com.itheima.prize.commons.db.mapper.CardGameMapper;
import com.itheima.prize.commons.db.service.CardGameService;
import com.itheima.prize.commons.utils.ApiResult;
import com.itheima.prize.commons.utils.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("/api/act")
@Api(tags = {"抽奖模块"})
public class ActController {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private LuaScript luaScript;

    @GetMapping("/limits/{gameid}")
    @ApiOperation(value = "剩余次数")
    @ApiImplicitParams({
            @ApiImplicitParam(name="gameid",value = "活动id",example = "1",required = true)
    })
    public ApiResult<Object> limits(@PathVariable int gameid, HttpServletRequest request){
        //获取活动基本信息
        CardGame game = (CardGame) redisUtil.get(RedisKeys.INFO+gameid);
        if (game == null){
            return new ApiResult<>(-1,"活动未加载",null);
        }
        //获取当前用户
        HttpSession session = request.getSession();
        CardUser user = (CardUser) session.getAttribute("user");
        if (user == null){
            return new ApiResult(-1,"未登陆",null);
        }
        //用户可抽奖次数
        Integer enter = (Integer) redisUtil.get(RedisKeys.USERENTER+gameid+"_"+user.getId());
        if (enter == null){
            enter = 0;
        }
        //根据会员等级，获取本活动允许的最大抽奖次数
        Integer maxenter = (Integer) redisUtil.hget(RedisKeys.MAXENTER+gameid,user.getLevel()+"");
        //如果没设置，默认为0，即：不限制次数
        maxenter = maxenter==null ? 0 : maxenter;

        //用户已中奖次数
        Integer count = (Integer) redisUtil.get(RedisKeys.USERHIT+gameid+"_"+user.getId());
        if (count == null){
            count = 0;
        }
        //根据会员等级，获取本活动允许的最大中奖数
        Integer maxcount = (Integer) redisUtil.hget(RedisKeys.MAXGOAL+gameid,user.getLevel()+"");
        //如果没设置，默认为0，即：不限制次数
        maxcount = maxcount==null ? 0 : maxcount;

        //幸运转盘类，先给用户随机剔除，再获取令牌，有就中，没有就说明抢光了
        //一般这种情况会设置足够的商品，卡在随机上
        Integer randomRate = (Integer) redisUtil.hget(RedisKeys.RANDOMRATE+gameid,user.getLevel()+"");
        if (randomRate == null){
            randomRate = 100;
        }

        Map map = new HashMap();
        map.put("maxenter",maxenter);
        map.put("enter",enter);
        map.put("maxcount",maxcount);
        map.put("count",count);
        map.put("randomRate",randomRate);

        return new ApiResult<>(1,"成功",map);
    }
    @GetMapping("/go/{gameid}")
    @ApiOperation(value = "抽奖")
    @ApiImplicitParams({
            @ApiImplicitParam(name="gameid",value = "活动id",example = "1",required = true)
    })
    public ApiResult<Object> act(@PathVariable int gameid, HttpServletRequest request){
        //TODO
        HttpSession session = request.getSession();
        CardUser user = (CardUser) session.getAttribute("user");
        if(user==null){
            return new ApiResult(-1,"未登录",null);
        }
        Integer userId = user.getId();
        //从redis获取活动基本信息
        CardGame cardGame = (CardGame) redisUtil.get(RedisKeys.INFO + gameid);
        //判断时间是否开始
        if(cardGame==null||new Date().before(cardGame.getStarttime())){
            return new ApiResult(-1,"活动未开始",null);
        }
        //判断活动是否结束
        if(new Date().after(cardGame.getEndtime())){
            return new ApiResult(-1,"活动已结束",null);
        }
        //判断抽奖次数是否用完
        //获取当前抽奖次数
        Object value =  redisUtil.get(RedisKeys.USERENTER + gameid + "_" + userId);
        int userEnter=value!=null? (int) value :0;
        if(userEnter==0){
            //将用户参与活动异步持久化到数据库
            CardUserGame cardUserGame = new CardUserGame();
            cardUserGame.setUserid(userId);
            cardUserGame.setGameid(gameid);
            cardUserGame.setCreatetime(new Date());
            rabbitTemplate.convertAndSend(RabbitKeys.EXCHANGE_DIRECT,RabbitKeys.QUEUE_PLAY,JSON.toJSONString(cardUserGame));
        }
        //获取最大抽奖次数
        Integer maxEnter = (Integer) redisUtil.hget(RedisKeys.MAXENTER + gameid, user.getLevel() + "");
        maxEnter=maxEnter==null?0:maxEnter;
        if(maxEnter!=0&&userEnter>=maxEnter){
            return new ApiResult(-1,"您的抽奖次数已用完",null);
        }
        //获取最大中奖次数
        Integer maxHit = (Integer) redisUtil.hget(RedisKeys.MAXGOAL + gameid, user.getLevel() + "");
        maxHit=maxHit==null?0:maxEnter;
        //抽奖次数增加1
        redisUtil.incr(RedisKeys.USERENTER + gameid + "_" + userId,1);
        //令牌校验
        Long check = luaScript.tokenCheck(gameid, userId, maxHit);
        if(check==0){
            return new ApiResult(-1,"未中奖",null);
        }else if(check==-1){
            return new ApiResult(-1,"您已达到最大抽奖次数",null);
        }else if(check==-2){
            return new ApiResult(-1,"奖品已抽光",null);
        }
        //中奖，查询奖品信息
        CardProductDto product = (CardProductDto) redisUtil.get(RedisKeys.TOKEN + gameid +"_"+check);
        //中奖后异步处理，持久化中奖信息
        CardUserHit cardUserHit = new CardUserHit();
        cardUserHit.setUserid(userId);
        cardUserHit.setGameid(gameid);
        cardUserHit.setProductid(product.getId());
        cardUserHit.setHittime(new Date());
        rabbitTemplate.convertAndSend(RabbitKeys.EXCHANGE_DIRECT,RabbitKeys.QUEUE_HIT,JSON.toJSONString(cardUserHit));

        return new ApiResult(1,"恭喜中奖",product);

    }

    @GetMapping("/info/{gameid}")
    @ApiOperation(value = "缓存信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name="gameid",value = "活动id",example = "1",required = true)
    })
    public ApiResult info(@PathVariable int gameid){
        //TODO
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map<String,Object> result=new HashMap<>();
        Object gameInfo = redisUtil.get(RedisKeys.INFO + gameid);
        result.put(RedisKeys.INFO + gameid,gameInfo);
        List<Object> lists = redisUtil.lrange(RedisKeys.TOKENS+gameid, 0, -1);
        Map<Object,Object> tokens=new HashMap<>();
        for (Object list : lists) {
            Object o = redisUtil.get(RedisKeys.TOKEN + gameid + "_" + list);
            tokens.put(simpleDateFormat.format(new Date((Long) list/1000))+"."+(Long) list%1000,o);
        }
        result.put(RedisKeys.TOKENS+gameid,tokens);
        Map<Object, Object> maxGoalMap = redisUtil.hmget(RedisKeys.MAXGOAL + gameid);
        result.put(RedisKeys.MAXGOAL+gameid,maxGoalMap);
        Map<Object, Object> maxEnterMap = redisUtil.hmget(RedisKeys.MAXENTER + gameid);
        result.put(RedisKeys.MAXENTER+gameid,maxEnterMap);
        return new ApiResult(1,"成功",result);
    }
}
